/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.di.ban.jr.rest.util;

import cn.ac.iie.di.ban.jr.rest.global.GlobalParas;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @author zwlin
 */
public class FileAppender {

	private static HashMap<String, FileAppender> appenderMap = new HashMap<>();

	public static synchronized void register(String name, FileAppender appender) {
		appenderMap.put(name, appender);
	}

	public static FileAppender getAppender(String name) {
		return appenderMap.get(name);
	}

	private static final String SPLITTER = ".";
	boolean activated;

	File dir;
	String fileDir;
	HashMap<String, String> nameMap;
	int maxSize;
	int interval;

	long last;
	Timer timer;

	int size;
	int seq;

	long startTime;
	long endTime;

	BufferedWriter bw;

	ReentrantLock lock;

	public FileAppender(String dirString, String filename, int size, int interval) throws IOException {
		initArg(dirString, filename, size, interval);
		initDefault();
		passOldFiles();
//		bw = new BufferedWriter(new FileWriter(new File(dir, name + SPLITTER + seq)));
	}

	private void initArg(String dirString, String filename, int size, int interval) {
		this.dir = new File(dirString);
		if (!this.dir.exists()) {
			if (!this.dir.mkdirs()) {
				throw new Error("cannot mkdir dir path:" + dirString);
			}
		} else if (!dir.isDirectory()) {
			throw new Error("dir path:" + dirString + " is not a directory.");
		}
		this.fileDir = dirString;
//		this.nameMap = filename == null ? "" : filename;
		this.maxSize = size * 1024 * 1024 / 4;
		this.interval = interval * 60 * 1000;
		this.startTime = System.currentTimeMillis();
		timer = new Timer("FileChangeTimer_" + filename);
	}

	private void initDefault() {

		last = Long.MAX_VALUE;
		size = 0;
		seq = 0;
		lock = new ReentrantLock();
		activated = false;
	}

	private void passOldFiles() {
		String[] files = dir.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
//				return name != null && name.startsWith(FileAppender.this.name);
				return false;
			}
		});
		int max = -1;
		for (String f : files) {
			String[] dvd = f.split(SPLITTER);
			if (dvd.length == 2) {
				try {
					int v = Integer.parseInt(dvd[1].trim());
					if (v > max) {
						max = v;
					}
				} catch (Exception e) {
				}
			}
		}
		seq = max + 1;
	}

	public void start() {
//		timer.schedule(new ChangeFileTask(), interval);
		activated = true;
	}

	public void stop() throws IOException {
		activated = false;
		timer.cancel();
//		bw.flush();
//		bw.close();
	}

//	class ChangeFileTask extends TimerTask {
//
//		@Override
//		public void run() {
//			if (System.currentTimeMillis() - last >= interval) {
//				lock.lock();
//				try {
//					if (System.currentTimeMillis() - last >= interval && size > 0) {
//						changeFile();
//					}
//					timer.schedule(ChangeFileTask.this, last + interval - System.currentTimeMillis());
//
//				} catch (IOException ex) {
//					throw new Error(ex);
//				} finally {
//					lock.unlock();
//				}
//			}
//		}
//	}

	public synchronized void append(String datatype, String str) throws IOException {
		if (!activated) {
			throw new Error("FileAppender is closed!");
		}
		lock.lock();
		try {
//			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
//			fileDir = GlobalParas.FILE_DIR + sdf.format(System.currentTimeMillis()) + "/";
			fileDir = WriteFile.getFileDir(GlobalParas.FILE_DIR, datatype);
			endTime = System.currentTimeMillis();
			if (size > maxSize || endTime - startTime > interval) {
				nameMap.put(datatype, WriteFile.getFileName("wxyq_" + datatype + "_"));
				size = 0;
				startTime = endTime;
			}
			size += str.length();
			WriteFile writeFile = new WriteFile(fileDir, nameMap.get(datatype));
			writeFile.writeFileAppend(datatype, str);
//			bw.write(str);
//			bw.newLine();
			last = System.currentTimeMillis();

		} finally {
			lock.unlock();
		}
	}

	public String getFileDir() {
		return fileDir;
	}

//	public String getName() {
////		return name;
////	}
//	private synchronized void changeFile() throws IOException {
////		bw.flush();
////		bw.close();
////		bw = new BufferedWriter(new FileWriter(new File(dir, name + SPLITTER + (++seq))));
//		Date date = new Date();
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
//		String dateNowStr = sdf.format(date);
//		name = "wxyq_dayhot_" + dateNowStr;
//		size = 0;
//	}

}
